package com.bestv.search.management.command;

import com.bestv.search.common.cache.SiteCache;
import com.bestv.search.common.dataSource.DataSourceKey;
import com.bestv.search.common.dataSource.DataSourceKeyUtil;
import com.bestv.search.common.model.*;
import com.bestv.search.common.model.uid.UID;
import com.bestv.search.common.service.InfoManager;
import com.bestv.search.common.service.ManualBindManager;
import com.bestv.search.common.util.DateUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.text.ParseException;
import java.util.*;

public class ManualBindCommand {
    protected final Log log = LogFactory.getLog(getClass());

    private ManualBindManager manualBindManager;
    private InfoManager infoManager;

    public InfoManager getInfoManager() {
        return infoManager;
    }

    public void setInfoManager(InfoManager infoManager) {
        this.infoManager = infoManager;
    }

    public ManualBindManager getManualBindManager() {
        return manualBindManager;
    }

    public void setManualBindManager(ManualBindManager manualBindManager) {
        this.manualBindManager = manualBindManager;
    }

    public String save(SysUser user, Map<String, String[]> map, DataSourceKey dsKey) throws ParseException {
        String result = "";
        String[] id = map.get("id");
        String[] name = map.get("name");
        String[] vdate = map.get("vdate");
        String[] invdate = map.get("invdate");
        String[] tags = map.get("tags");
        String[] infoCodes = map.get("infoCode");
        String[] scs = map.get("sc");// mb.sites
        String[] globleSC = map.get("globleSC");// BestvSearch.sc

        ArrayList<String> codes = new ArrayList<String>();
        if (infoCodes != null)
            for (String infoCode : infoCodes)
                codes.add(infoCode);

        // 存在性判断
        ManualBind existed = manualBindManager.getManualBindByName(dsKey, name[0]);
        if (existed != null) {
            if ("".equals(id[0]))
                return "[existed]";
            if (Long.valueOf(id[0]) != existed.getId())
                return "[existed]";
        }
        // 开始save操作
        String[] sites = null;
        ManualBind manualBind = null;
        if (id == null || "".equals(id[0])) {// new
            manualBind = new ManualBind();
            manualBind.setCreator(user);
            manualBind.setCreateTime(new Date());
            manualBind.setOwner(SiteCache.map.get(globleSC[0]));
            manualBind.setId(new Long(UID.getUID(manualBind)));
            if (scs == null || "".equals(scs[0]))
                sites = new String[]{user.getSite().getCode()};
            else
                sites = scs[0].split(",");
            Set<Site> siteSet = new HashSet<Site>(10);
            for (String siteCode : sites) {
                siteSet.add(SiteCache.map.get(siteCode));
            }
            if (siteSet.size() > 0)
                manualBind.setSites(siteSet);
        } else {
            // update
            manualBind = manualBindManager.getManualBindById(dsKey, new Long(id[0]));
            Set<Site> ss = manualBind.getSites();
            sites = new String[ss.size()];
            int i = 0;
            for (Site s : ss)
                sites[i++] = s.getCode();
        }

        manualBind.setName(name[0]);
        manualBind.setTags(tags[0]);
        if (vdate != null && !"".equals(vdate[0])) {
            Date startTime = DateUtil.convertStringToDate("yyyy-MM-dd HH:mm", vdate[0]);
            manualBind.setStartTime(startTime);
        }
        if (invdate != null && !"".equals(invdate[0])) {
            Date endTime = DateUtil.convertStringToDate("yyyy-MM-dd HH:mm", invdate[0]);
            manualBind.setEndTime(endTime);
        }
        manualBindManager.saveManualBindAll(dsKey, manualBind, codes, infoManager);
        result = "{'result':'success','message':'}";
        return result;
    }

    protected String update(SysUser user, String name, String vdate, String invdate, String tags, String siteCode,
                            Long id, List<Long> infoIds) throws ParseException {
        DataSourceKey key = DataSourceKeyUtil.convert(siteCode);
        ManualBind mb = manualBindManager.getManualBindById(key, id);
        if (mb == null)
            return "[error]";
        mb.setCreator(user);
        mb.setCreateTime(new Date());
        mb.setName(name);
        mb.setTags(tags);
        if (!"".equals(vdate)) {
            Date startTime = DateUtil.convertStringToDate("yyyy-MM-dd HH:mm", vdate);
            mb.setStartTime(startTime);
        }
        if (!"".equals(invdate)) {
            Date endTime = DateUtil.convertStringToDate("yyyy-MM-dd HH:mm", invdate);
            mb.setEndTime(endTime);
        }
        if (mb.getInfos() != null)
            mb.getInfos().clear();
        if (infoIds != null && infoIds.size() > 0) {
            Set<Info> infos = infoManager.getInfoSetByIds(key, infoIds);
            mb.setInfos(infos);
        }
        manualBindManager.saveManualBind(key, mb);
        return "{'result':'success','message':''}";
    }

    public String get(SysUser user, Map<String, String[]> map, DataSourceKey dsKey) throws JSONException {
        String[] id = map.get("id");

        ManualBind mb = manualBindManager.getManualBindById(dsKey, new Long(id[0]));

        JSONObject jo = new JSONObject();
        jo.put("name", mb.getName());
        jo.put("startDate", DateUtil.convertDateToString("yyyy-MM-dd HH:mm", mb.getStartTime()));
        jo.put("endDate", DateUtil.convertDateToString("yyyy-MM-dd HH:mm", mb.getEndTime()));
        jo.put("tags", mb.getTags());
        // if("HDQ".equals(siteCode[0])){
        Set<Site> sites = mb.getSites();
        if (sites != null && sites.size() > 0) {
            StringBuffer sb = new StringBuffer();
            for (Site site : sites)
                sb.append(site.getName()).append(";");
            sb.deleteCharAt(sb.length() - 1);
            jo.put("sites", sb.toString());
        }
        // }else
        return jo.toString();
    }

    public String delete(SysUser user, Map<String, String[]> map, DataSourceKey dsKey) {
        String[] id = map.get("id");
        if ("".equals(id[0]))
            return "{'result':'failure','message':'idnull'}";

        ManualBind mb = manualBindManager.getManualBindById(dsKey, new Long(id[0]));
        if (mb == null)
            return "{'result':'failure','message':'idnull'}";
        manualBindManager.deleteManualBindAll(dsKey, mb);
        return "{'result':'success','message':''}";
    }

    public String find(SysUser user, Map<String, String[]> map, DataSourceKey dsKey) throws JSONException {
        String result = "";
        String[] start = map.get("start");
        String[] limit = map.get("limit");

        int stat = 0, lmt = 20;
        if ("".equals(start[0]))
            stat = -1;
        else
            stat = Integer.parseInt(start[0]);
        if ("".equals(limit))
            lmt = -1;
        else
            lmt = Integer.parseInt(limit[0]);
        int count = 0;
        JSONArray array = new JSONArray();

        if ("HDQ".equals(dsKey)) {
            // look for HDQ Site
            count = manualBindManager.getOwnsCount(dsKey);
            if (count == 0)
                return "{'totalCount':0,'manualBinds':[]}";
            List<ManualBind> hdqList = manualBindManager.getOwns(dsKey, stat, lmt);
            for (ManualBind mb : hdqList)
                array.put(manualBindToJSONObject(mb, dsKey.toString()));
        } else {// look for normal site
            if ("HDQ".equals(user.getSite().getCode())) {
                count = manualBindManager.getListIncludeFailedMbsCount(dsKey);
                if (count == 0)
                    return "{'totalCount':0,'manualBinds':[]}";
                List<ManualBind> mbSet = manualBindManager.getManualBinds(dsKey, stat, lmt);
                for (ManualBind mb : mbSet)
                    array.put(manualBindToJSONObject(mb, dsKey.toString()));
            } else {
                count = manualBindManager.getManualBindCount(dsKey);
                if (count == 0)
                    return "{'totalCount':0,'manualBinds':[]}";
                List<ManualBind> siteList = manualBindManager.getManualBinds(dsKey, stat, lmt);
                for (ManualBind mb : siteList)
                    array.put(manualBindToJSONObject(mb, dsKey.toString()));
            }
        }
        result = "{'totalCount':" + count + ",'manualBinds':" + array.toString() + "}";
        return result;
    }

    public String findBindInfosByMbId(SysUser user, Map<String, String[]> map, DataSourceKey dsKey)
            throws JSONException {
        String[] id = map.get("id");

        if (id == null || "".equals(id[0]))
            return "[idNull]";
        JSONArray array = new JSONArray();

        if ("HDQ".equals(dsKey.toString())) {
            ManualBind mb = manualBindManager.getManualBindById(dsKey, new Long(id[0]));
            if (mb.getInfos() == null || mb.getInfos().size() == 0)
                return "[noInfoBind]";
            for (Info info : mb.getInfos())
                array.put(infoToJSONObject(info));
            return "{'effect':'','infos':" + array.toString() + "}";
        }
        Set<Info> infoExisted = null, infoNotExiested = null;

        ManualBind mb = manualBindManager.getManualBindById(dsKey, new Long(id[0]));
        if ("HDQ".equals(mb.getOwner().getCode())) {// mb不是一个皮
            Set<Info> infos = mb.getInfos();
            if (infos == null || infos.size() == 0)
                return "{'effect':'noBindInfo','infos':[]}";
            Map<Long, Info> infoMap = new HashMap<Long, Info>();
            for (Info info : infos)
                infoMap.put(info.getId(), info);
            Set<Info> infoFromSC = infoManager.getInfoSetByIds(dsKey, infoMap.keySet());
            for (Info info : infoFromSC)
                infos.remove(infoMap.get(info.getId()));
            infoExisted = infoFromSC;
            infoNotExiested = infos;
        } else {
            // 驻地已生效，但是mb在总部仅仅是个皮
            mb = manualBindManager.getManualBindById(dsKey, new Long(id[0]));
            infoExisted = mb.getInfos();
        }

        if ((infoExisted == null || infoExisted.size() == 0)
                && (infoNotExiested == null || infoNotExiested.size() == 0))
            return "{'effect':'noBindInfo','infos':[]}";
        String effect;
        if (infoNotExiested == null || infoNotExiested.size() == 0) {// 已生效
            effect = "y";
            for (Info info : infoExisted) {
                JSONObject jo = infoToJSONObject(info);
                jo.put("existed", "y");
                array.put(jo);
            }
        } else {// 未生效
            effect = "n";
            for (Info info : infoNotExiested) {
                JSONObject jo = infoToJSONObject(info);
                jo.put("existed", "n");
                array.put(jo);
            }
            if (infoExisted != null && infoExisted.size() > 0) {
                for (Info info : infoExisted) {
                    JSONObject jo = infoToJSONObject(info);
                    jo.put("existed", "y");
                    array.put(jo);
                }
            }
        }
        return "{'effect':'" + effect + "','infos':" + array.toString() + "}";
    }

    private JSONObject infoToJSONObject(Info info) throws JSONException {
        JSONObject jo = new JSONObject();
        jo.put("id", info.getId());
        jo.put("name", info.getName());
        jo.put("p_type", info.getP_type());
        jo.put("updateTime",
                info.getUpdateTime() == null ? "" : DateUtil.convertDateToString("yyyy-MM-dd HH:mm",
                        info.getUpdateTime()));
        Set<Keyword> keySet = info.getKeywords();
        if (keySet == null || keySet.size() == 0)
            jo.put("keywords", "");
        else {
            StringBuffer sb = new StringBuffer();
            int i = 0;
            for (Keyword key : keySet) {
                sb.append(key.getKeyword());
                if (++i < keySet.size())
                    sb.append(",");
            }
            jo.put("keywords", sb.toString());
        }
        Set<Tag> tagSet = info.getTags();
        if (tagSet == null || tagSet.size() == 0)
            jo.put("tags", "");
        else {
            StringBuffer tagBf = new StringBuffer();
            int i = 0;
            for (Tag t : tagSet) {
                tagBf.append(t.getTag());
                if (++i < tagSet.size())
                    tagBf.append(",");
            }
            jo.put("tags", tagBf.toString());
        }
        if (info instanceof Entrance)
            jo.put("type", info.getType() == null ? "" : info.getType().getName());
        else if (info instanceof Program) {
            jo.put("type", info.getType() == null ? "" : info.getType().getName());
        } else if (info instanceof Series) {
            jo.put("type", info.getType() == null ? "" : info.getType().getName());
        } else if (info instanceof Schedule) {
            Schedule p = (Schedule) info;
            if (p.getEndPlayTime().before(new Date()))
                jo.put("type", "回看");
            else
                jo.put("type", "预告");
        }
        return jo;
    }

    private JSONObject manualBindToJSONObject(ManualBind mb, String sc) throws JSONException {
        JSONObject jo = new JSONObject();
        jo.put("id", String.valueOf(mb.getId()));
        jo.put("name", mb.getName());
        jo.put("creator", mb.getCreator().getUsername() + ":" + mb.getCreator().getSite().getName());
        jo.put("createTime",
                mb.getCreateTime() == null ? "" : DateUtil.convertDateToString("yyyy-MM-dd", mb.getCreateTime()));
        jo.put("tags", mb.getTags());
        jo.put("startTime",
                mb.getStartTime() == null ? "" : DateUtil.convertDateToString("yyyy-MM-dd HH:mm", mb.getStartTime()));
        jo.put("endTime",
                mb.getEndTime() == null ? "" : DateUtil.convertDateToString("yyyy-MM-dd HH:mm", mb.getEndTime()));

        Set<Site> sites = mb.getSites();
        if (sites != null) {
            StringBuffer nb = new StringBuffer();
            StringBuffer cb = new StringBuffer();
            for (Site site : sites) {
                nb.append(site.getName()).append(" ");
                cb.append(site.getCode()).append(" ");
            }
            jo.put("sites", cb.append("&").append(nb));
        } else
            jo.put("sites", "");
        Date d = new Date();
        if (mb.getStartTime().before(d) && mb.getEndTime().after(d))
            jo.put("failed", 2);// 2表示生效
        else if (mb.getStartTime().before(d))
            jo.put("failed", 3);// 已过期
        else
            jo.put("failed", 1);// 尚未生效
        jo.put("owner", mb.getOwner().getCode());

        return jo;
    }
}
